#ifndef __EVENTLOOP_H__
#define __EVENTLOOP_H__

#include "MutexLock.h"
#include <sys/epoll.h>
#include <vector>
#include <map>
#include <memory>
#include <functional>

using std::vector;
using std::map;
using std::shared_ptr;
using std::function;

class Acceptor;//前向声明
class TcpConnection;//前向声明

using TcpConnectionPtr = shared_ptr<TcpConnection>;
using TcpConnectionCallback = function<void(const TcpConnectionPtr &)>;
using Functor = function<void()>;

class EventLoop
{
public:
    EventLoop(Acceptor &accptor);
    ~EventLoop();

    //循环进行还是没有进行
    void loop();
    void unloop();

    //注册三个回调，交给数据成员
    void setNewConnectionCallback(TcpConnectionCallback &&cb);
    void setMessageCallback(TcpConnectionCallback &&cb);
    void setCloseCallback(TcpConnectionCallback &&cb);

private:
    //封装epoll_wait的函数
    void waitEpollFd();

    //处理新的连接
    void handleNewConnection();
    //处理消息的收发
    void handleMessage(int fd);

    //创建文件描述符_epfd
    int createEpollFd();
    //将文件描述符放在红黑树上进行监听
    void addEpollReadFd(int fd);
    //将文件描述符从红黑树上摘除
    void delEpollReadFd(int fd);

public:
    void wakeup();
private:
    void handleRead();
    int createEventFd();
    //执行所有的“任务”
    void doPengdingFunctors();
public:
    void runInLoop(Functor &&cb);

private:
    //add cache
    int createTimerFd();
    void addTimerReadFd(int fd);
    void handleTimerRead();
    void doCacheFunctor();

private:
    int _epfd;//epoll_create创建文件描述符
    int _evtfd;//eventfd创建的文件描述符，用于通信
    vector<struct epoll_event> _evtlist;//存放满足条件的文件描述符集合
    bool _isLooping;//标识循环是否在进行
    Acceptor &_acceptor;//需要调用Acceptor中的accept函数
    map<int, TcpConnectionPtr> _conns;//存放文件描述符与连接的键值对

    TcpConnectionCallback _onNewConnectionCb;//1、连接建立
    TcpConnectionCallback _onMessageCb;//2、消息到达
    TcpConnectionCallback _onCloseCb;//3、连接断开

    //EventLoop中存放在vector中的任务是：发送的数据msg以及发送数据能力的
    //TcpConnection中的send函数
    vector<Functor> _pengdings;//存放待执行的“任务”
    MutexLock _mutex;//互斥访问vector
    
    // add cache
    int _timerfd;
};

#endif
